import re
from django.utils.translation import gettext_lazy as _, gettext_lazy
from django.conf import settings

from api import exceptions
from api.serializers import NextCloudExternalMountsSerializer, NextCloudMountSerializer
from buckets.handlers.nextcloud_db import NextcloudDBError, NextcloudHandler
from buckets.models import Bucket, NextcloudMounts
from ceph.models import GlobalConfig
from logrecord.manager import user_operation_record
from users.auth.views import *
from users.models import UserProfile

from utils.view import CustomGenericViewSet


def is_valid_email(user_):
    """验证邮箱字符串的有效性"""

    if user_.email:
        return user_.email

    # 正则表达式用于匹配邮箱地址
    email_regex = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'

    # 使用 re.match() 方法进行匹配
    if re.match(email_regex, user_.username):
        return user_.username

    raise exceptions.BadRequest(message=f'邮箱信息未验证通过')


class NextcloudDBUserError(exceptions.Error):
    """"""
    default_status_code = status.HTTP_400_BAD_REQUEST


def check_resource_permissions(request):
    """检查资源管理员"""
    # 资源管理员
    resource_user = GlobalConfig.objects.filter(name=GlobalConfig.ConfigName.RESOURCE_ADMINISTRATOR.value).first()

    if not resource_user:
        return False

    resource_user_list = GlobalConfig.parse_lines(text=resource_user.content)
    if request.user.username in resource_user_list:
        return True

    return False


class NextCloudViewSet(CustomGenericViewSet):
    """挂在存储桶到 nextcloud"""

    queryset = []
    # permission_classes = [APIIPPermission, IsAuthenticated]
    permission_classes = [IsAuthenticated]
    lookup_field = 'bucket_name'
    lookup_value_regex = '[a-z0-9-_]{3,64}'

    @swagger_auto_schema(
        operation_summary=_('资源管理员/用户：列出nextcloud服务中的存储桶'),
        request_body=no_body,
        manual_parameters=[
            openapi.Parameter(
                name='owner', in_=openapi.IN_QUERY,
                type=openapi.TYPE_BOOLEAN,
                default=False,
                description=gettext_lazy("显示所有的桶（超级用户和资源管理员使用）"),
                required=False
            )
        ],
        responses={
        }
    )
    def list(self, request, *args, **kwargs):
        """
        列出nextcloud服务中的存储桶

            >>Http Code: 状态码200,成功：
                {
                  "count": 1,
                  "next": null,
                  "previous": null,
                  "results": [
                    {
                      "id": 16,
                      "user_email": "wanghuang@cnic.cn",
                      "bucket_name": "test-wang"
                    }
                  ]
                }

        """

        queryset_all = NextcloudMounts.objects.all()

        # 资源管理员 -
        if check_resource_permissions(request=request) or request.user.is_superuser:

            is_owner = request.query_params.get('owner', None)
            if is_owner == 'false':
                self.queryset = queryset_all.filter(user_id=request.user.id)
            else:
                self.queryset = queryset_all
        else:
            self.queryset = queryset_all.filter(user_id=request.user.id)

        queryset = self.filter_queryset(self.get_queryset())
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    @swagger_auto_schema(
        operation_summary=_('资源管理员/用户：存储桶信息同步到nextcloud'),
        request_body=no_body,
        manual_parameters=[
            openapi.Parameter(
                name='user_id', in_=openapi.IN_QUERY,
                type=openapi.TYPE_INTEGER,
                description=gettext_lazy("用户id（资源管理员和超级管理员有效）"),
                required=False
            ),
            openapi.Parameter(
                name='aai_id', in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                description=gettext_lazy("aai_id,用户nextcloud 创建用户信息"),
                required=True
            ),
        ],
        responses={
            status.HTTP_200_OK: """
           {'code': 201, 'code_text': '信息同步成功'}
        """
        }
    )
    def create_detail(self, request, *args, **kwargs):
        """
        nextcloud 挂载存储桶 不能使用 桶token操作


            >>Http Code: 状态码201：
            {'code': 201, 'code_text': '信息同步成功'}

            >>Http Code: 400 401 403 500
            {
                'code': "BadRequest",   // AccessDenied、InternalError、
                'code_text': '参数有误'
            }
        """

        nextcloud_s3_url = getattr(settings, 'NEXTCLOUD_S3_SERVICE_URL', None)
        if not nextcloud_s3_url or 'x.x.x.x' in nextcloud_s3_url:
            exc = exceptions.Error(f'nextcloud s3 url 未设置，请联系管理员。')
            return Response(data=exc.err_data_old(), status=exc.status_code)

        if not request.user.is_authenticated:
            return Response({'code': 403, 'code_text': 'You do not have access permissions'},
                            status=status.HTTP_403_FORBIDDEN)

        bucket = None
        user_ = None
        email = None
        user_id = request.query_params.get('user_id', None)
        aai_id = request.query_params.get('aai_id', None)
        bucket_name = kwargs.get(self.lookup_field, '')

        if not aai_id:
            return Response({'code': 400, 'code_text': 'aai_id is required'},
                            status=status.HTTP_400_BAD_REQUEST)

        if check_resource_permissions(request=request):
            if not user_id:
                exc = exceptions.BadRequest(f'请填写用户信息。')
                return Response(data=exc.err_data_old(), status=exc.status_code)

            try:
                user_ = self.get_user(user_id=user_id)
            except exceptions.BadRequest as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)

        elif request.user.is_superuser and user_id:

            try:
                user_ = self.get_user(user_id=user_id)
            except exceptions.BadRequest as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)

        elif request.user.is_superuser and not user_id:  # 给超级管理员自己挂载
            user_ = request.user

        if user_:  # 管理员和资源管理员

            try:
                bucket = self.get_user_bucket(id_or_name=bucket_name, by_name=True, user=user_)
                email = is_valid_email(user_)
            except exceptions.Error as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)

        elif not user_id:  #

            try:
                bucket = self.get_user_bucket(id_or_name=bucket_name, by_name=True, user=request.user)
                email = is_valid_email(request.user)
            except exceptions.Error as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)
            user_ = request.user

        elif user_id:
            exc = exceptions.BadRequest(f'无效操作')
            return Response(data=exc.err_data_old(), status=exc.status_code)

        s3_key = AuthKey.objects.filter(user=user_, state=True, permission=0).first()
        if not s3_key:

            s3_key = AuthKey(user=user_)
            try:
                s3_key.save()
            except Exception as e:
                return Response({'code': 500, 'code_text': 'Create key failed'},
                                status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # 不能重复挂载

        exist_nextcloud_bucket = NextcloudMounts.objects.filter(user_id=user_id, bucket_name=bucket_name).first()
        if exist_nextcloud_bucket:
            exc = exceptions.BadRequest(f'存储桶已经存在nextcloud服务中，不能重复操作。如果出现其他情况，请联系管理员。')
            return Response(data=exc.err_data_old(), status=exc.status_code)

        try:
            NextcloudHandler().add_bucket_nextcloud(email=email, nextcloud_s3_url=nextcloud_s3_url, bucket=bucket,
                                                    s3_key=s3_key, user=user_, aai_id=aai_id)

        except NextcloudDBError as exc:
            return Response(data=exc.err_data_old(), status=exc.status_code)

        except exceptions.BadRequest as exc:
            return Response(data=exc.err_data_old(), status=exc.status_code)

        except exceptions.Error as exc:
            return Response(data=exc.err_data_old(), status=exc.status_code)

        except Exception as e:
            exc = exceptions.Error(str(e))
            return Response(data=exc.err_data_old(), status=exc.status_code)

        user_operation_record.add_log(request=request,
                                      operation_content=f'存储桶:{bucket.name} 信息同步到 nextcloud服务中',
                                      real_user=user_.username)

        return Response(data={'code': 201, 'code_text': '信息同步成功'}, status=status.HTTP_201_CREATED)

    @swagger_auto_schema(
        operation_summary=_('资源管理员/用户：删除nextcloud中的存储桶'),
        request_body=no_body,
        manual_parameters=[
            openapi.Parameter(
                name='user_id', in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                description=gettext_lazy("用户id(资源管理员和超级管理员有效)"),
                required=False
            ),
        ],
        responses={
            status.HTTP_200_OK: """
            {'code': 200, 'code_text': '信息删除成功'}
            """
        }
    )
    def destroy(self, request, *args, **kwargs):
        """
        删除 nextcloud 存储桶信息

            >>Http Code: 状态码204：
            {'code': 204, 'code_text': '信息删除成功'}

            >>Http Code: 400 401 403 500
            {
                'code': "BadRequest",   // AccessDenied、InternalError、
                'code_text': '参数有误'
            }

        """
        bucket_name = kwargs.get(self.lookup_field, '')

        bucket = None
        user_ = None
        user_id = request.query_params.get('user_id', None)

        # 资源管理员 -
        if check_resource_permissions(request=request):

            user_id = request.query_params.get('user_id', None)
            if not user_id:
                exc = exceptions.Error(f'请填写用户信息。')
                return Response(data=exc.err_data_old(), status=exc.status_code)

            try:
                user_ = self.get_user(user_id=user_id)
            except exceptions.BadRequest as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)

        elif request.user.is_superuser and user_id:
            try:
                user_ = self.get_user(user_id=user_id)
            except exceptions.BadRequest as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)

        elif request.user.is_superuser:
            user_ = request.user

        if user_:
            try:
                bucket = self.get_user_bucket(id_or_name=bucket_name, by_name=True, user=user_)
            except exceptions.Error as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)

        elif not user_id:  # 普通用户
            user_ = request.user
            try:
                bucket = self.get_user_bucket(id_or_name=bucket_name, by_name=True, user=user_)
            except exceptions.Error as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)

        elif user_id:
            exc = exceptions.BadRequest(f'无效操作')
            return Response(data=exc.err_data_old(), status=exc.status_code)

        # 查看nextcloud 数据库是否存在该用户
        try:
            NextcloudHandler().delete_bucket_nextcloud(bucket=bucket)
        except NextcloudDBUserError as exc:
            return Response(data=exc.err_data_old(), status=exc.status_code)

        except exceptions.BadRequest as exc:
            return Response(data=exc.err_data_old(), status=exc.status_code)

        except exceptions.Error as exc:
            return Response(data=exc.err_data_old(), status=exc.status_code)

        except Exception as e:
            exc = exceptions.Error(str(e))
            return Response(data=exc.err_data_old(), status=exc.status_code)

        user_operation_record.add_log(request=request,
                                      operation_content=f'存储桶:{bucket.name} 信息从 nextcloud服务中移除',
                                      real_user=user_.username)

        return Response(data={'code': 200, 'code_text': '信息删除成功'}, status=200)

    @swagger_auto_schema(
        operation_summary=_('资源管理员/用户：更改nextcloud服务中存储桶密钥'),
        request_body=no_body,
        manual_parameters=[
            openapi.Parameter(
                name='user_id', in_=openapi.IN_QUERY,
                type=openapi.TYPE_INTEGER,
                description=_("用户id (资源管理员或超级管理员有效)"),
                required=False
            ),
            openapi.Parameter(
                name='access_key', in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                description=_("访问密钥"),
                required=True
            ),
            openapi.Parameter(
                name='secret_key', in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                description=_("私秘秘钥"),
                required=True
            ),
        ]
    )
    def partial_update(self, request, *args, **kwargs):
        """
            修改nextcloud服务中存储桶的密钥信息

                >>Http Code: 状态码204：
                {'code': 201, 'code_text': '信息修改成功'}

                >>Http Code: 400 401 403 500
                {
                    'code': "BadRequest",   // AccessDenied、InternalError、
                    'code_text': '参数有误'
                }

        """
        bucket_name = kwargs.get(self.lookup_field, '')
        user_id = request.query_params.get('user_id', None)
        access_key = request.query_params.get('access_key', None)
        secret_key = request.query_params.get('secret_key', None)

        user_ = None
        bucket_id = None

        if not access_key or not secret_key:
            return Response({'code': 400, 'code_text': '缺少 access_key 参数'}, status=status.HTTP_400_BAD_REQUEST)

        if check_resource_permissions(request=request):  # 资源管理员
            if not user_id:
                exc = exceptions.BadRequest(f'请填写用户信息。')
                return Response(data=exc.err_data_old(), status=exc.status_code)

            try:
                user_ = self.get_user(user_id=user_id)
            except exceptions.BadRequest as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)

        elif request.user.is_superuser and user_id:

            try:
                user_ = self.get_user(user_id=user_id)
            except exceptions.BadRequest as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)

        elif request.user.is_superuser and not user_id:  # 给超级管理员自己挂载
            user_ = request.user

        if user_:  # 管理员和资源管理员

            try:
                bucket = self.get_user_bucket(id_or_name=bucket_name, by_name=True, user=user_)
            except exceptions.Error as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)

            bucket_id = bucket.id

        elif not user_id:  #

            try:
                bucket = self.get_user_bucket(id_or_name=bucket_name, by_name=True, user=request.user)
            except exceptions.Error as exc:
                return Response(data=exc.err_data_old(), status=exc.status_code)

            user_ = request.user
            bucket_id = bucket.id

        elif user_id:
            exc = exceptions.BadRequest(f'无效操作')
            return Response(data=exc.err_data_old(), status=exc.status_code)

        # 查询nextcloud挂载信息
        try:
            NextcloudHandler().update_nextcloud_bucket_s3key(bucket_id=bucket_id, s3_key=access_key,
                                                             s3_secret=secret_key)

        except exceptions.BadRequest as exc:
            return Response(data=exc.err_data_old(), status=exc.status_code)

        except Exception as e:
            exc = exceptions.Error(f'{str(e)}')
            return Response(data=exc.err_data_old(), status=exc.status_code)

        user_operation_record.add_log(request=request,
                                      operation_content=f'存储桶:{bucket_name} 访问密钥和私秘秘钥信息更新到 nextcloud服务中',
                                      real_user=user_.username)

        return Response(data={'code': 201, 'code_text': '信息修改成功'}, status=status.HTTP_201_CREATED)

    @swagger_auto_schema(
        operation_summary=_('资源管理员/超级管理员：删除nextcloud服务中的用户信息'),
        request_body=no_body,
        manual_parameters=[
            openapi.Parameter(
                name='aai_id', in_=openapi.IN_QUERY,
                type=openapi.TYPE_STRING,
                description=_("aai id"),
                required=True
            )
        ],
    )
    @action(detail=False, methods=['delete'], url_path='user')
    def delete_nextcloud_user(self, request, *args, **kwargs):
        """
        删除 nextlcoud 服务中的用户信息

            >>Http Code: 状态码204

            >>Http Code: 400 401 403 500
            {
                'code': "BadRequest",   // AccessDenied、InternalError、
                'code_text': '参数有误'
            }
        """

        aai_id = request.query_params.get('aai_id', None)
        if not aai_id:
            return Response({'code': 400, 'code_text': '缺少 aai_id 参数'}, status=status.HTTP_400_BAD_REQUEST)

        if not check_resource_permissions(request=request):
            if not request.user.is_superuser:  # 资源管理员
                exc = exceptions.AuthenticationFailed()
                return Response(data=exc.err_data_old(), status=exc.status_code)

        # 查询 nextcloud 桶表是否有该桶的挂载信息
        try:
            NextcloudHandler().delete_nextcloud_user(aai_id)
        except Exception as e:
            exc = exceptions.BadRequest(str(e))
            return Response(data=exc.err_data_old(), status=exc.status_code)

        user_operation_record.add_log(request=request,
                                      operation_content=f'删除 nextlcoud 服务中的用户：{aai_id}')

        return Response(status=status.HTTP_204_NO_CONTENT)

    @staticmethod
    def get_user_bucket(id_or_name: str, by_name: bool = False, user=None):
        """
        获取存储桶对象，并检测用户访问权限

        :return:
            Bucket()

        :raises: Error
        """
        if by_name:
            bucket = Bucket.objects.select_related('user').filter(name=id_or_name).first()
        else:
            try:
                bid = int(id_or_name)
            except Exception as e:
                raise exceptions.BadRequest(message=_('无效的存储桶ID'))

            bucket = Bucket.objects.filter(id=bid).first()

        if not bucket:
            raise exceptions.NoSuchBucket(message=_('存储桶不存在'))

        if bucket.check_user_own_bucket(user):
            return bucket
        exc = exceptions.AccessDenied(message=_('你没有此存储桶的访问权限'))
        raise exc

    def get_user(self, user_id):
        """"""
        user_ = UserProfile.objects.filter(id=int(user_id)).first()
        if not user_:
            raise exceptions.BadRequest(f'未找到用户信息。')

        # if not user_.email:
        #     raise exceptions.BadRequest(f'请完善邮箱信息')

        return user_

    def get_serializer_class(self):

        if self.action == 'create_detail':
            return NextCloudExternalMountsSerializer
        if self.action == 'list':
            return NextCloudMountSerializer

        return Serializer
